home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Graphics / sKulpt / skulpt-src / win-src / Objects-Base-.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-13  |  29.9 KB  |  1,062 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16.  
  17. // Includes utilitaires D3D
  18. #include "d3dmath.h"
  19. #include "d3dutil.h"
  20. #include "D3DEnum.h"
  21.  
  22. #include <d3dx.h>
  23.  
  24. // Ids Resources
  25. #include "resource.h"
  26.  
  27. // Constantes
  28. #include "const.h"
  29.  
  30. // Types
  31. #include "types.h"
  32.  
  33. // Variables globales projet
  34. #include "vars.h"
  35.  
  36. // Prototypes fonctions autres modules
  37. #include "proto.h"
  38.  
  39. // Macros
  40. #include "macros.h"
  41.  
  42. //************************************* C O M M U N S ***********************
  43. void vDeleteObjects(void)
  44. {
  45.     // RAZ points
  46.     for (int iVert = 0 ; iVert < XDC_NUMPT ; iVert++)
  47.     {
  48.         Vertices[iVert].bEnabled = FALSE;
  49.         Vertices[iVert].bHidden = FALSE;
  50.         Vertices[iVert].bSelected = FALSE;
  51.         Vertices[iVert].bSmooth = FALSE;
  52.         Vertices[iVert].iDepend = 0;
  53.     }
  54.     iVertFirstAvailable = 0;
  55.     iVertLastUsed = -1;
  56.  
  57.     // RAZ arêtes
  58.     for (int iEdge = 0 ; iEdge < XDC_NUMEDGE ; iEdge++)
  59.     {
  60.         Edges[iEdge].bEnabled = FALSE;
  61.         Edges[iEdge].bHidden = FALSE;
  62.     }
  63.     iEdgeFirstAvailable = 0;
  64.     iEdgeLastUsed = -1;
  65.  
  66.     // RAZ lampes
  67.     for (int iLamp = 0 ; iLamp < XDC_NUMLAMP ; iLamp++)
  68.         if (Lampes[iLamp].bEnabled) bDeleteLamp(iLamp);
  69.  
  70.     iLampFirstAvailable = 0;
  71.     iLampLastUsed = -1;
  72.  
  73.     // RAZ facettes
  74.     for (int iTriangle = 0 ; iTriangle < XDC_NUMTRI ; iTriangle++)
  75.     {
  76.         Triangles[iTriangle].bEnabled = FALSE;
  77.         Triangles[iTriangle].bHidden = FALSE;
  78.     }
  79.     iTriaFirstAvailable = 0;
  80.     iTriaLastUsed = -1;
  81.  
  82.     // RAZ Objets D3D
  83.     vDeleteD3DObjects();
  84. }
  85.  
  86. //************************************** V E R T E X *************************
  87. int iFindVertex(D3DVECTOR p, int iPrevious)
  88. {
  89.     int iCnt;
  90.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  91.     
  92.     // Rechercher le point
  93.     for (iCnt = max(iPrevious + 1, 0) ;
  94.             (iCnt <= iVertLastUsed)
  95.          && (!(   (Vertices[iCnt].bEnabled == TRUE)
  96.                && (Vertices[iCnt].bHidden == FALSE)
  97.                && (fabs(Vertices[iCnt].vPoint.x - p.x) < fTolerance)
  98.                && (fabs(Vertices[iCnt].vPoint.y - p.y) < fTolerance)
  99.                && (fabs(Vertices[iCnt].vPoint.z - p.z) < fTolerance)
  100.               ))
  101.          ;
  102.          iCnt++) ;
  103.  
  104.     // Si point trouvé alors renvoyer son indice
  105.     if (iCnt <= iVertLastUsed)
  106.         return(iCnt);
  107.  
  108.     // Sinon renvoyer -1
  109.     return -1;
  110. }
  111.  
  112. int iMakeVertex(D3DVECTOR p, BOOL bSame)
  113. {
  114.     int iCnt;
  115.     
  116.     // Rechercher le premier index libre
  117.     for (iCnt = bSame ? 0 : iVertFirstAvailable ;
  118.             (iCnt <= iVertLastUsed)
  119.          && (   ((!bSame) && (Vertices[iCnt].bEnabled == TRUE))
  120.              || ((bSame) && (!((Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))))
  121.             ) ;
  122.          iCnt++) ;
  123.  
  124.     // Si limite tableau atteinte alors renvoyer erreur
  125.     if (iCnt >= XDC_NUMPT)
  126.     {
  127.         vTrace("*** E0016 : Plus de slots vertex libres");
  128.         return -1;
  129.     }
  130.  
  131.     // Si point trouvé dans tableau alors le renvoyer
  132.     if (bSame)
  133.     {
  134.         if ((iCnt < XDC_NUMPT) && (Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))
  135.             return(iCnt);
  136.         else
  137.             return(iMakeVertex(p, XDC_FORCENEW));
  138.     }
  139.  
  140.     // Créer un nouveau point
  141.     Vertices[iCnt].vPoint = p;
  142.     Vertices[iCnt].bSelected = FALSE;
  143.     Vertices[iCnt].bHidden = FALSE;
  144.     Vertices[iCnt].bEnabled  =TRUE;
  145.  
  146.     while (Vertices[iVertFirstAvailable].bEnabled == TRUE) iVertFirstAvailable++;
  147.     if (iVertLastUsed < iCnt) iVertLastUsed = iCnt;
  148.  
  149.     return iCnt;
  150. }
  151.  
  152. BOOL bVertInEdge(int iVert, int iEdge)
  153. {
  154.     if (    (Edges[iEdge].iSommets[0] == iVert)
  155.          || (Edges[iEdge].iSommets[1] == iVert)
  156.        )
  157.         return TRUE;
  158.     else
  159.         return FALSE;
  160. }
  161.  
  162. BOOL bVertInTriangle(int iVert, int iTriangle)
  163. {
  164.     if (    (Triangles[iTriangle].iSommets[0] == iVert)
  165.          || (Triangles[iTriangle].iSommets[1] == iVert)
  166.          || (Triangles[iTriangle].iSommets[2] == iVert)
  167.        )
  168.         return TRUE;
  169.     else
  170.         return FALSE;
  171. }
  172.  
  173. int iEdgesPerVert(int iVert)
  174. {
  175.     int iCnt, jCnt = 0;
  176.  
  177.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  178.         if (bVertInEdge(iVert, iCnt))
  179.             jCnt++;
  180.  
  181.     return jCnt;
  182. }
  183.  
  184. int iTrianglesPerVert(int iVert)
  185. {
  186.     int iCnt, jCnt = 0;
  187.  
  188.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  189.         if (bVertInTriangle(iVert, iCnt))
  190.             jCnt++;
  191.  
  192.     return jCnt;
  193. }
  194.  
  195. BOOL bDeleteVertex(int iVert)
  196. {
  197.     int iCnt;
  198.  
  199.     // Si le point n'est as enabled alors ne rien faire
  200.     if (Vertices[iVert].bEnabled == FALSE) return FALSE;
  201.  
  202.     // Disabler le point
  203.     Vertices[iVert].bEnabled = FALSE;
  204.     
  205.     // Mettre à jour les indices globaux du tableau des vertices
  206.     if (iVert == iVertLastUsed) while (!Vertices[--iVertLastUsed].bEnabled) ;
  207.     if (iVert < iVertFirstAvailable) iVertFirstAvailable = iVert;
  208.  
  209.     // Supprimer toutes les arêtes desquelles le sommet supprimé est une extrêmité
  210.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  211.         if (bVertInEdge(iVert, iCnt))
  212.             bDeleteEdge(iCnt);
  213.  
  214.     // Pour tout triangle duquel le sommet supprimé est un sommet, transformer le triangle en une arête entre les 2 sommets restants
  215.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  216.         if (bVertInTriangle(iVert, iCnt))
  217.         {
  218.             /*
  219.             if (Triangles[iCnt].iSommets[0] == iVert) iMakeEdge(Triangles[iCnt].iSommets[1], Triangles[iCnt].iSommets[2]);
  220.             if (Triangles[iCnt].iSommets[1] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[2]);
  221.             if (Triangles[iCnt].iSommets[2] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[1]);
  222.             */
  223.             bDeleteTriangle(iCnt);
  224.         }
  225.  
  226.     return TRUE;
  227. }
  228.  
  229. BOOL bSmoothNorm(int iVertex)
  230. {
  231.     if (Vertices[iVertex].bEnabled == FALSE) return FALSE;
  232.     if (Vertices[iVertex].bSmooth == FALSE) return FALSE;
  233.     if (Vertices[iVertex].iDepend == 0) return FALSE;
  234.  
  235.     D3DVECTOR vn = D3DVECTOR(0.f, 0.f, 0.f);
  236.  
  237.     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  238.     {
  239.         if (Triangles[iTriangle].bEnabled == FALSE) continue;
  240.         if (!bVertInTriangle(iVertex, iTriangle)) continue;
  241.  
  242.         D3DVECTOR vc;
  243. /*
  244.         short iS0 = Triangles [iTriangle].iSommets[0],
  245.               iS1 = Triangles [iTriangle].iSommets[1],
  246.               iS2 = Triangles [iTriangle].iSommets[2];
  247.  
  248.         D3DVECTOR
  249.                 v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  250.                 v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  251.                 v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  252.                 vn0, vn1, vn2;
  253.  
  254.         vn0 = Normalize(CrossProduct(v01, v02));
  255.         vn1 = Normalize(CrossProduct(v01, v12));
  256.         vn2 = Normalize(CrossProduct(v02, v12));
  257.  
  258. */
  259.         for (int iCnt = 0 ; iCnt < 3 ; iCnt++)
  260.             if (iVertex == Triangles [iTriangle].iSommets[iCnt])
  261.                 vc = D3DVECTOR(
  262.                     Triangles [iTriangle].pSommets[iCnt].nx,
  263.                     Triangles [iTriangle].pSommets[iCnt].ny,
  264.                     Triangles [iTriangle].pSommets[iCnt].nz);
  265.  
  266. /*
  267.         if (iVertex == iS0) vc = vn0;
  268.         if (iVertex == iS1) vc = vn1;
  269.         if (iVertex == iS2) vc = vn2;
  270.  
  271.         float fdp = DotProduct(vn, vc);
  272.  
  273.         if (fdp >= 0)
  274. */
  275.             vn += vc;
  276. /*
  277.         else
  278.             vn -= vc;
  279. */
  280.     }
  281.  
  282.     Vertices[iVertex].vNormal = Normalize(vn);
  283.  
  284.     return TRUE;
  285. }
  286.  
  287. BOOL bIsVertexSelected(int iVertex)
  288. {
  289.     return
  290.         Vertices[iVertex].bEnabled && Vertices[iVertex].bSelected;
  291. }
  292.  
  293. //************************************** L A M P E S *************************
  294. int iFindLamp(D3DVECTOR p, int iPrevious)
  295. {
  296.     int iCnt;
  297.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  298.     
  299.     // Rechercher la lampe
  300.     for (iCnt = max(iPrevious + 1, 0) ;
  301.             (iCnt <= iLampLastUsed)
  302.          && (!(   (Lampes[iCnt].bEnabled == TRUE)
  303.                && (fabs(Lampes[iCnt].lLamp.dvPosition.x - p.x) < fTolerance)
  304.                && (fabs(Lampes[iCnt].lLamp.dvPosition.y - p.y) < fTolerance)
  305.                && (fabs(Lampes[iCnt].lLamp.dvPosition.z - p.z) < fTolerance)
  306.               ))
  307.          ;
  308.          iCnt++) ;
  309.  
  310.     // Si point trouvé alors renvoyer son indice
  311.     if (iCnt <= iLampLastUsed)
  312.         return(iCnt);
  313.  
  314.     // Sinon renvoyer -1
  315.     return -1;
  316. }
  317.  
  318. int iMakeLamp(
  319.     D3DLIGHTTYPE    dltType,            /* Type of light source */
  320.     D3DCOLORVALUE   dcvDiffuse,         /* Diffuse color of light */
  321.     D3DCOLORVALUE   dcvSpecular,        /* Specular color of light */
  322.     D3DCOLORVALUE   dcvAmbient,         /* Ambient color of light */
  323.     D3DVECTOR       dvPosition,         /* Position in world space */
  324.     D3DVECTOR       dvDirection,        /* Direction in world space */
  325.     D3DVALUE        dvRange,            /* Cutoff range */
  326.     D3DVALUE        dvFalloff,          /* Falloff */
  327.     D3DVALUE        dvAttenuation0,     /* Constant attenuation */
  328.     D3DVALUE        dvAttenuation1,     /* Linear attenuation */
  329.     D3DVALUE        dvAttenuation2,     /* Quadratic attenuation */
  330.     D3DVALUE        dvTheta,            /* Inner angle of spotlight cone */
  331.     D3DVALUE        dvPhi               /* Outer angle of spotlight cone */
  332. )
  333. {
  334.     int iCnt;
  335.     
  336.     // Rechercher le premier index libre
  337.     for (iCnt = iLampFirstAvailable ;
  338.             (iCnt <= iLampLastUsed)
  339.          && (Lampes[iCnt].bEnabled == TRUE) ;
  340.          iCnt++) ;
  341.  
  342.     // Si limite tableau atteinte alors renvoyer erreur
  343.     if (iCnt >= XDC_NUMLAMP)
  344.     {
  345.         vTrace("*** E0017 : Plus de slots vertex libres");
  346.         return -1;
  347.     }
  348.  
  349.     // Créer une nouvelle lampe
  350.     ZeroMemory(&Lampes[iCnt].lLamp, sizeof(D3DLIGHT7));
  351.     Lampes[iCnt].bEnabled = TRUE;
  352.     Lampes[iCnt].bSelected = FALSE;
  353.     Lampes[iCnt].bLit = TRUE;
  354.     Lampes[iCnt].lLamp.dltType = dltType; // D3DLIGHT_POINT ou D3DLIGHT_DIRECTIONAL ou D3DLIGHT_SPOT
  355.     Lampes[iCnt].lLamp.dcvDiffuse = dcvDiffuse;
  356.     Lampes[iCnt].lLamp.dcvSpecular = dcvSpecular;
  357.     Lampes[iCnt].lLamp.dcvAmbient = dcvAmbient;
  358.     Lampes[iCnt].lLamp.dvPosition = dvPosition;
  359.     Lampes[iCnt].lLamp.dvDirection = dvDirection;
  360.     Lampes[iCnt].lLamp.dvRange = dvRange;
  361.     Lampes[iCnt].lLamp.dvFalloff = dvFalloff;
  362.     Lampes[iCnt].lLamp.dvAttenuation0 = dvAttenuation0; 
  363.     Lampes[iCnt].lLamp.dvAttenuation1 = dvAttenuation1; 
  364.     Lampes[iCnt].lLamp.dvAttenuation2 = dvAttenuation2; 
  365.     Lampes[iCnt].lLamp.dvTheta = dvTheta; 
  366.     Lampes[iCnt].lLamp.dvPhi = dvPhi; 
  367.  
  368. #ifndef NO3D
  369.     lpd3dDevice->SetLight(iCnt, &Lampes[iCnt].lLamp);
  370.     lpd3dDevice->LightEnable(iCnt, Lampes[iCnt].bLit);
  371. #endif
  372.  
  373.     while (Lampes[iLampFirstAvailable].bEnabled == TRUE) iLampFirstAvailable++;
  374.     if (iLampLastUsed < iCnt) iLampLastUsed = iCnt;
  375.  
  376.     return iCnt;
  377. }
  378.  
  379. BOOL bUpdateLamp(int iLamp)
  380. {
  381.     // Si la lampe n'est pas enabled alors ne rien faire
  382.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  383.  
  384. #ifndef NO3D
  385.     lpd3dDevice->SetLight(iLamp, &Lampes[iLamp].lLamp);
  386.     lpd3dDevice->LightEnable(iLamp, Lampes[iLamp].bLit);
  387. #endif
  388.  
  389.     return TRUE;
  390. }
  391.  
  392. BOOL bDeleteLamp(int iLamp)
  393. {
  394.     // Si la lampe n'est pas enabled alors ne rien faire
  395.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  396.  
  397.     // Disabler la lampe
  398. #ifndef NO3D
  399.     lpd3dDevice->LightEnable(iLamp, FALSE);
  400. #endif
  401.     Lampes[iLamp].bEnabled = FALSE;
  402.     Lampes[iLamp].bLit = FALSE;
  403.     
  404.     // Mettre à jour les indices globaux du tableau des lampes
  405.     if (iLamp == iLampLastUsed) while (!Lampes[--iLampLastUsed].bEnabled) ;
  406.     if (iLamp < iLampFirstAvailable) iLampFirstAvailable = iLamp;
  407.  
  408.     return TRUE;
  409. }
  410.  
  411. //************************************** E D G E S ***************************
  412. int iFindEdge(int i1, int i2)
  413. {
  414.     int iCnt;
  415.  
  416.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  417.         if (    ((Edges[iCnt].iSommets[0] == i1) || (Edges[iCnt].iSommets[1] == i1))
  418.              && ((Edges[iCnt].iSommets[0] == i2) || (Edges[iCnt].iSommets[1] == i2))
  419.            )
  420.            return iCnt;
  421.  
  422.     return -1;
  423. }
  424.  
  425. int iMakeEdge(int i1, int i2)
  426. {
  427.     int iCnt;
  428.  
  429.     // Rechercher un slot d'arête libre
  430.     for (iCnt = iEdgeFirstAvailable ; (iCnt <= iEdgeLastUsed) && (Edges [iCnt].bEnabled == TRUE) ; iCnt++);
  431.  
  432.     // Si pas trouvé alors fail
  433.     if (iCnt >= XDC_NUMEDGE)
  434.     {
  435.         vTrace("*** E0018 : Plus de slots arêtes libres");
  436.         return -1;
  437.     }
  438.  
  439.     // Créer l'arête
  440.     Edges [iCnt].iSommets[0] = i1;
  441.     Edges [iCnt].iSommets[1] = i2;
  442.  
  443.     Edges[iCnt].bEnabled = TRUE;
  444.     Edges[iCnt].bHidden = FALSE;
  445.  
  446.     while (Edges[iEdgeFirstAvailable].bEnabled == TRUE) iEdgeFirstAvailable++;
  447.     if (iEdgeLastUsed < iCnt) iEdgeLastUsed = iCnt;
  448.     
  449.     return iCnt;
  450. }
  451.  
  452. BOOL bDeleteEdge(int iEdge)
  453. {
  454.     // Si l'arête n'est pas enabled alors ne rien faire
  455.     if (Edges[iEdge].bEnabled == FALSE) return FALSE;
  456.  
  457.     // Disabler l'arête
  458.     Edges[iEdge].bEnabled = FALSE;
  459.     
  460.     // Mettre à jour les indices globaux du tableau des arêtes
  461.     if (iEdge == iEdgeLastUsed) while (!Edges[--iEdgeLastUsed].bEnabled) ;
  462.     if (iEdge < iEdgeFirstAvailable) iEdgeFirstAvailable = iEdge;
  463.  
  464.     return TRUE;
  465. }
  466.  
  467. BOOL    bIsEdgeSelected(int iEdge)
  468. {
  469.     return
  470.         Edges[iEdge].bEnabled &&
  471.         bIsVertexSelected(Edges[iEdge].iSommets[0]) &&
  472.         bIsVertexSelected(Edges[iEdge].iSommets[1]);
  473. }
  474.  
  475. BOOL    bIsEdgePartiallySelected(int iEdge)
  476. {
  477.     return 
  478.         Edges[iEdge].bEnabled &&
  479.         (bIsVertexSelected(Edges[iEdge].iSommets[0]) ||
  480.          bIsVertexSelected(Edges[iEdge].iSommets[1]));
  481. }
  482.  
  483. //************************************** T R I A N G L E S *******************
  484. int iFindTriangle(int i1, int i2, int i3)
  485. {
  486.     int iCnt;
  487.  
  488.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  489.         if (    ((Triangles[iCnt].iSommets[0] == i1) || (Triangles[iCnt].iSommets[1] == i1) || (Triangles[iCnt].iSommets[2] == i1))
  490.              && ((Triangles[iCnt].iSommets[0] == i2) || (Triangles[iCnt].iSommets[1] == i2) || (Triangles[iCnt].iSommets[2] == i2))
  491.              && ((Triangles[iCnt].iSommets[0] == i3) || (Triangles[iCnt].iSommets[1] == i3) || (Triangles[iCnt].iSommets[2] == i3))
  492.            )
  493.            return iCnt;
  494.  
  495.     return -1;
  496. }
  497.  
  498. int iMakeTriangle(int i1, int i2, int i3, unsigned char bRouge, unsigned char bVert, unsigned char bBleu)
  499. {
  500.     int iCnt;
  501.  
  502.     // Rechercher un slot de triangle libre
  503.     for (iCnt = iTriaFirstAvailable ; (iCnt <= iTriaLastUsed) && (Triangles [iCnt].bEnabled == TRUE) ; iCnt++);
  504.  
  505.     // Si pas trouvé alors fail
  506.     if (iCnt >= XDC_NUMTRI)
  507.     {
  508.         vTrace("*** E0019 : Plus de slots triangles libres");
  509.         return -1;
  510.     }
  511.  
  512.     // Créer le triangle
  513.     Triangles [iCnt].iSommets[0] = i1;
  514.     Triangles [iCnt].iSommets[1] = i2;
  515.     Triangles [iCnt].iSommets[2] = i3;
  516.  
  517.     // Incrémenter le compteur de triangles des sommets
  518.     Vertices[Triangles [iCnt].iSommets[0]].iDepend++;
  519.     Vertices[Triangles [iCnt].iSommets[1]].iDepend++;
  520.     Vertices[Triangles [iCnt].iSommets[2]].iDepend++;
  521.  
  522.     // Affecter couleur et aspect
  523.     D3DMATERIAL7 *pMtrl = &Triangles[iCnt].mtrl;
  524.     ZeroMemory(pMtrl, sizeof(D3DMATERIAL7));
  525.     pMtrl -> ambient.a = 0.5f;
  526.     pMtrl -> ambient.r = (float) bRouge / 255.f / 6.f;
  527.     pMtrl -> ambient.g = (float) bVert / 255.f / 6.f;
  528.     pMtrl -> ambient.b = (float) bBleu / 255.f / 6.f;
  529.  
  530.     pMtrl -> diffuse.a = 0.5f;
  531.     pMtrl -> diffuse.r = (float) bRouge / 255.f;
  532.     pMtrl -> diffuse.g = (float) bVert / 255.f;
  533.     pMtrl -> diffuse.b = (float) bBleu / 255.f;
  534.  
  535.     pMtrl -> specular.a = 0.5f;
  536.     pMtrl -> specular.r = 1.f;
  537.     pMtrl -> specular.g = 1.f;
  538.     pMtrl -> specular.b = 1.f;
  539.     pMtrl -> power = 1.f;
  540.  
  541.     Triangles[iCnt].bEnabled = TRUE;
  542.     Triangles[iCnt].bHidden = FALSE;
  543.  
  544.     // Mettre à jour les coordonnées du triangle D3D correspondant
  545.     bUpdateD3DTri(iCnt);
  546.  
  547.     while (Triangles[iTriaFirstAvailable].bEnabled == TRUE) iTriaFirstAvailable++;
  548.     if (iTriaLastUsed < iCnt) iTriaLastUsed = iCnt;
  549.     
  550.     return iCnt;
  551. }
  552.  
  553. BOOL bDeleteTriangle(int iTriangle)
  554. {
  555.     // Si le triangle n'est pas enabled alors ne rien faire
  556.     if (Triangles[iTriangle].bEnabled == FALSE) return FALSE;
  557.  
  558.     // Disabler le triangle
  559.     Triangles[iTriangle].bEnabled = FALSE;
  560.     
  561.     // Mettre à jour les indices globaux du tableau des triangles
  562.     if (iTriangle == iTriaLastUsed) while (!Triangles[--iTriaLastUsed].bEnabled) ;
  563.     if (iTriangle < iTriaFirstAvailable) iTriaFirstAvailable = iTriangle;
  564.  
  565.     // Décrémenter le compteur de triangles des sommets
  566.     Vertices[Triangles [iTriangle].iSommets[0]].iDepend--;
  567.     Vertices[Triangles [iTriangle].iSommets[1]].iDepend--;
  568.     Vertices[Triangles [iTriangle].iSommets[2]].iDepend--;
  569.  
  570.     return TRUE;
  571. }
  572.  
  573. BOOL bUpdateD3DTri(int iCnt)
  574. {
  575.     if (Triangles[iCnt].bEnabled == FALSE) return FALSE;
  576.     
  577.     short iS0 = Triangles [iCnt].iSommets[0],
  578.           iS1 = Triangles [iCnt].iSommets[1],
  579.           iS2 = Triangles [iCnt].iSommets[2];
  580.  
  581.     D3DVECTOR
  582.             v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  583.             v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  584.             v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  585.             vn0, vn1, vn2,
  586.             v1, v2, vp2, v3, v4;
  587.     
  588.     D3DMATRIX p;
  589.  
  590.     // Calculer la normale au point 0 : v3
  591.     v1 = Normalize(v01);
  592.     v2 = Normalize(v02);
  593.     v3 = Normalize(CrossProduct(v01, v02));
  594.     
  595.     // On fait un repère orthonormal avec v3 et v1 (qui sont orthonormés) et leur produit vectoriel
  596.     vp2 = Normalize(CrossProduct(v3, v1));
  597.  
  598.     // On fait la matrice de changement de repère 
  599.     D3DUtil_SetIdentityMatrix(p);
  600.     p._11 = v1.x;
  601.     p._21 = v1.y;
  602.     p._31 = v1.z;
  603.     p._12 = vp2.x;
  604.     p._22 = vp2.y;
  605.     p._32 = vp2.z;
  606.     p._13 = v3.x;
  607.     p._23 = v3.y;
  608.     p._33 = v3.z;
  609.  
  610.     // on calcule l'image de z dans le nouveau repère : v4
  611.     D3DMath_VectorMatrixMultiply(v4, D3DVECTOR(0.f, 0.f, 1.f), p);
  612.  
  613.     // On vérifie que v4 est dans le même sens que z, ce qui nous dit si le triangle est CW ou CCW
  614.     float fSign = DotProduct(D3DVECTOR(0.f, 0.f, 1.f), v4);
  615.  
  616.     // On calcule les vecteurs normaux
  617.     if (Vertices[iS0].bSmooth) { bSmoothNorm(iS0); vn0 = Vertices[iS0].vNormal; }
  618.     else vn0 = Normalize(CrossProduct(v01, v02));
  619.  
  620.     if (Vertices[iS1].bSmooth) { bSmoothNorm(iS1); vn1 = Vertices[iS1].vNormal; }
  621.     else vn1 = Normalize(CrossProduct(v01, v12));
  622.  
  623.     if (Vertices[iS2].bSmooth) { bSmoothNorm(iS2); vn2 = Vertices[iS2].vNormal; }
  624.     else vn2 = Normalize(CrossProduct(v02, v12));
  625.  
  626.     // Créer les 2 triangles D3D (CW, CCW) en ordonnant les sommets pour avoir les CCW en 1er
  627.     if (fSign >= 0)
  628.     {
  629.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  630.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  631.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  632.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  633.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  634.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  635.     }
  636.     else
  637.     {
  638.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  639.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  640.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  641.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  642.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  643.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  644.     }
  645.  
  646.     return TRUE;
  647. }
  648.  
  649. BOOL bSubdivideTriangle(int iTriangle)
  650. {
  651.     int iNewV[3], iNewT[4];
  652.     
  653.     if (Triangles[iTriangle].bEnabled == FALSE) return(FALSE);
  654.  
  655.     unsigned char uR = (unsigned char) (Triangles[iTriangle].mtrl.diffuse.r * 255.f),
  656.                   uG = (unsigned char) (Triangles[iTriangle].mtrl.diffuse.g * 255.f),
  657.                   uB = (unsigned char) (Triangles[iTriangle].mtrl.diffuse.b * 255.f);
  658.  
  659.     if (-1 == (iNewV[0] = iMakeVertex(
  660.                 (Vertices[Triangles[iTriangle].iSommets[0]].vPoint +
  661.                  Vertices[Triangles[iTriangle].iSommets[1]].vPoint
  662.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  663.  
  664.     if (-1 == (iNewV[1] = iMakeVertex(
  665.                 (Vertices[Triangles[iTriangle].iSommets[1]].vPoint +
  666.                  Vertices[Triangles[iTriangle].iSommets[2]].vPoint
  667.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  668.  
  669.     if (-1 == (iNewV[2] = iMakeVertex(
  670.                 (Vertices[Triangles[iTriangle].iSommets[2]].vPoint +
  671.                  Vertices[Triangles[iTriangle].iSommets[0]].vPoint
  672.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  673.  
  674.     if (-1 == (iNewT[0] = iMakeTriangle(iNewV[0], iNewV[1], iNewV[2], uR, uG, uB))) return FALSE;
  675.     if (-1 == (iNewT[1] = iMakeTriangle(iNewV[0], iNewV[1], Triangles[iTriangle].iSommets[1], uR, uG, uB))) return FALSE;
  676.     if (-1 == (iNewT[2] = iMakeTriangle(iNewV[1], iNewV[2], Triangles[iTriangle].iSommets[2], uR, uG, uB))) return FALSE;
  677.     if (-1 == (iNewT[3] = iMakeTriangle(iNewV[0], iNewV[2], Triangles[iTriangle].iSommets[0], uR, uG, uB))) return FALSE;
  678.  
  679.     Vertices[iNewV[0]].bSelected =
  680.     Vertices[iNewV[1]].bSelected =
  681.     Vertices[iNewV[2]].bSelected = Vertices[Triangles[iTriangle].iSommets[0]].bSelected;
  682.  
  683.     return bDeleteTriangle(iTriangle);
  684. }
  685.  
  686. BOOL    bIsTriangleSelected(int iTriangle)
  687. {
  688.     return
  689.         Triangles[iTriangle].bEnabled &&
  690.         bIsVertexSelected(Triangles[iTriangle].iSommets[0]) &&
  691.         bIsVertexSelected(Triangles[iTriangle].iSommets[1]) &&
  692.         bIsVertexSelected(Triangles[iTriangle].iSommets[2]);
  693. }
  694.  
  695. BOOL    bIsTrianglePartiallySelected(int iTriangle)
  696. {
  697.     return 
  698.         Triangles[iTriangle].bEnabled &&
  699.         (bIsVertexSelected(Triangles[iTriangle].iSommets[0]) ||
  700.          bIsVertexSelected(Triangles[iTriangle].iSommets[1]) ||
  701.          bIsVertexSelected(Triangles[iTriangle].iSommets[2]));
  702. }
  703.  
  704. //********************************************** O U T I L S *************************
  705. // Propager de façon **non** récursive la dé/sélection d'un vertex aux vertices connexes (à travers edges ou triangles)
  706. void vPropagateSelection(void)
  707. {
  708.     register BOOL bReste;
  709.  
  710.     bReste = TRUE;
  711.     while (bReste)
  712.     {
  713.         bReste = FALSE;
  714.  
  715.         for (register int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  716.             if (bIsEdgePartiallySelected(iEdge) && !bIsEdgeSelected(iEdge))
  717.                 bReste =
  718.                 Vertices[Edges[iEdge].iSommets[0]].bSelected = 
  719.                 Vertices[Edges[iEdge].iSommets[1]].bSelected = TRUE;
  720.     }
  721.  
  722.     bReste = TRUE;
  723.     while (bReste)
  724.     {
  725.         bReste = FALSE;
  726.  
  727.         for (register int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  728.             if (bIsTrianglePartiallySelected(iTria) && !bIsTriangleSelected(iTria))
  729.                 bReste =
  730.                 Vertices[Triangles[iTria].iSommets[0]].bSelected = 
  731.                 Vertices[Triangles[iTria].iSommets[1]].bSelected = 
  732.                 Vertices[Triangles[iTria].iSommets[2]].bSelected = TRUE;
  733.     }
  734. }
  735.  
  736. // Cloner la sélection
  737. BOOL bCloneSelection(D3DVECTOR vShift, BOOL bCloneMode)
  738. {
  739.     int iCnt, jCnt, iNumSelected, *iIndex;
  740.  
  741.     // Compter les points sélectionnés
  742.     iNumSelected = 0;
  743.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  744.         if (bIsVertexSelected(iCnt)) iNumSelected++;
  745.  
  746.     if (!iNumSelected) return FALSE;
  747.  
  748.     // Allouer la table de correspondance ancien / nouvel index
  749.     iIndex = (int *) malloc(iNumSelected * 2 * sizeof(int));
  750.  
  751.     // Cloner les points sélectionnés en conservant la table de correspondance ancien / nouveau
  752.     // et en décalant les nouveaux de vShift
  753.     jCnt = 0;
  754.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  755.     {
  756.         D3DVECTOR vVect = Vertices[iCnt].vPoint + vShift;
  757.  
  758.         if (!bIsVertexSelected(iCnt)) continue;
  759.  
  760.         // Remplir la table de correspondance ancien / nouveau
  761.         iIndex[jCnt] = iCnt;
  762.         iIndex[jCnt + 1] = iMakeVertex(vVect, XDC_FORCENEW);
  763.         jCnt += 2;
  764.     }
  765.  
  766.     // Cloner les arêtes éventuelles entre les anciens points
  767.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  768.     {
  769.         if (Edges[iCnt].bEnabled == FALSE) continue;
  770.  
  771.         int iOVert1 = Edges[iCnt].iSommets[0],
  772.             iOVert2 = Edges[iCnt].iSommets[1],
  773.             iCVert1 = -1,
  774.             iCVert2 = -1;
  775.  
  776.         // Vérifier que les deux sommets originaux de l'arête sont sélectionnés
  777.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2))
  778.         {
  779.             // Alors il faut créer une nouvelle arête avec les sommets clonés
  780.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  781.             {
  782.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  783.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  784.             }
  785.             if ((iCVert1 != -1) && (iCVert2 != -1))
  786.             {
  787.                 iMakeEdge(iCVert1, iCVert2);
  788.  
  789.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  790.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  791.                 {
  792.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, 0xFF, 0xFF, 0xFF);
  793.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, 0xFF, 0xFF, 0xFF);
  794.                 }
  795.             }
  796.         }
  797.     }
  798.  
  799.     // Cloner les triangles éventuels entre les différents points
  800.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  801.     {
  802.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  803.  
  804.         int iOVert1 = Triangles[iCnt].iSommets[0],
  805.             iOVert2 = Triangles[iCnt].iSommets[1],
  806.             iOVert3 = Triangles[iCnt].iSommets[2],
  807.             iCVert1 = -1,
  808.             iCVert2 = -1,
  809.             iCVert3 = -1;
  810.  
  811.         // Vérifier que les trois sommets originaux du triangle sont sélectionnés
  812.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2) && bIsVertexSelected(iOVert3))
  813.         {
  814.             // Alors il faut créer un nouveau triangle avec les sommets clonés
  815.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  816.             {
  817.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  818.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  819.                 if (iIndex[jCnt * 2] == iOVert3) iCVert3 = iIndex[jCnt * 2 + 1];
  820.             }
  821.             if ((iCVert1 != -1) && (iCVert2 != -1) && (iCVert3 != -1))
  822.             {
  823.                 unsigned char uR = (unsigned char) (Triangles[iCnt].mtrl.diffuse.r * 255.f),
  824.                               uG = (unsigned char) (Triangles[iCnt].mtrl.diffuse.g * 255.f),
  825.                               uB = (unsigned char) (Triangles[iCnt].mtrl.diffuse.b * 255.f);
  826.  
  827.                 iMakeTriangle(iCVert1, iCVert2, iCVert3, uR, uG, uB);
  828.  
  829.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  830.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  831.                 {
  832.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, uR, uG, uB);
  833.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, uR, uG, uB);
  834.                     iMakeTriangle(iOVert2, iCVert2, iCVert3, uR, uG, uB);
  835.                     iMakeTriangle(iOVert2, iOVert3, iCVert3, uR, uG, uB);
  836.                     iMakeTriangle(iOVert1, iCVert1, iCVert3, uR, uG, uB);
  837.                     iMakeTriangle(iOVert1, iOVert3, iCVert3, uR, uG, uB);
  838.                 }
  839.             }
  840.         }
  841.     }
  842.  
  843.     // Inverser la sélection (sélectionner les nouveaux points)
  844.     for (iCnt = 0 ; iCnt < iNumSelected ; iCnt++)
  845.     {
  846.         Vertices[iIndex[iCnt * 2    ]].bSelected = FALSE;
  847.         Vertices[iIndex[iCnt * 2 + 1]].bSelected = TRUE;
  848.     }
  849.  
  850.     // Libérer la table de correspondance
  851.     free(iIndex);
  852.  
  853.     return TRUE;
  854. }
  855.  
  856. // Cacher les éléments de la sélection
  857. void vHideSelection(void)
  858. {
  859.     int iVert, iCnt;
  860.  
  861.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  862.     {
  863.         if (bIsVertexSelected(iVert))
  864.         {
  865.             Vertices[iVert].bHidden = TRUE;
  866.             Vertices[iVert].bSelected = FALSE;
  867.  
  868.             for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  869.             {
  870.                 if (Edges[iCnt].bEnabled == FALSE) continue;
  871.  
  872.                 if (bVertInEdge(iVert, iCnt))
  873.                     Edges[iCnt].bHidden = TRUE;
  874.             }
  875.             for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  876.             {
  877.                 if (Triangles[iCnt].bEnabled == FALSE) continue;
  878.  
  879.                 if (bVertInTriangle(iVert, iCnt))
  880.                     Triangles[iCnt].bHidden = TRUE;
  881.             }
  882.         }
  883.     }
  884. }
  885.  
  886. // Rendre visibles les éléments cachés
  887. void vRevealHidden(void)
  888. {
  889.     int iCnt;
  890.  
  891.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  892.     {
  893.         if (Vertices[iCnt].bEnabled == FALSE) continue;
  894.  
  895.         Vertices[iCnt].bHidden = FALSE;
  896.     }
  897.  
  898.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  899.     {
  900.         if (Edges[iCnt].bEnabled == FALSE) continue;
  901.  
  902.         Edges[iCnt].bHidden = FALSE;
  903.     }
  904.  
  905.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  906.     {
  907.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  908.  
  909.         Triangles[iCnt].bHidden = FALSE;
  910.     }
  911. }
  912.  
  913. // Déterminer le barycentre de la sélection
  914. D3DVECTOR vCenter(void)
  915. {
  916.     D3DVECTOR dVect = D3DVECTOR(0.f, 0.f, 0.f);
  917.     int jCnt = 0;
  918.  
  919.     for (int iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  920.         if (bIsVertexSelected(iVert))
  921.         {
  922.             // Mémoriser les coordonnées avant modification
  923.             Vertices[iVert].vPointBack = Vertices[iVert].vPoint;
  924.             
  925.             // Compter les points
  926.             jCnt++;
  927.  
  928.             // Additionner les coordonnées du point à celles du barycentre
  929.             dVect.x += Vertices[iVert].vPoint.x;
  930.             dVect.y += Vertices[iVert].vPoint.y;
  931.             dVect.z += Vertices[iVert].vPoint.z;
  932.         }
  933.  
  934.     if (!jCnt) 
  935.     {
  936.         vTrace("*** E0022 : Pas de sélection");
  937.         return dVect;
  938.     }
  939.  
  940.     // Moyenner la somme des points
  941.     dVect.x /= jCnt;
  942.     dVect.y /= jCnt;
  943.     dVect.z /= jCnt;
  944.  
  945.     return dVect;
  946. }
  947.  
  948. // Garbage collektor !-)
  949. void vCollect(void)
  950. {
  951.     int iShift, iVert, *iMapTo;
  952.  
  953.     // Réindexer les arêtes
  954.     iShift = 0;
  955.  
  956.     for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  957.     {
  958.         if (Edges[iEdge].bEnabled == FALSE)
  959.         {
  960.             while (Edges[iEdge + iShift].bEnabled == FALSE)
  961.             {
  962.                 iShift++;
  963.                 iEdgeLastUsed--;
  964.             }
  965.         }
  966.         if (iShift)
  967.         {
  968.             Edges[iEdge] = Edges[iEdge + iShift];
  969.             Edges[iEdge + iShift].bEnabled = FALSE;
  970.         }
  971.     }
  972.  
  973.     iEdgeFirstAvailable = iEdgeLastUsed + 1;
  974.  
  975.     // Réindexer les triangles
  976.     iShift = 0;
  977.  
  978.     for (int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  979.     {
  980.         if (Triangles[iTria].bEnabled == FALSE)
  981.         {
  982.             while (Triangles[iTria + iShift].bEnabled == FALSE)
  983.             {
  984.                 iShift++;
  985.                 iTriaLastUsed--;
  986.             }
  987.         }
  988.         if (iShift)
  989.         {
  990.             Triangles[iTria] = Triangles[iTria + iShift];
  991.             Triangles[iTria + iShift].bEnabled = FALSE;
  992.         }
  993.     }
  994.  
  995.     iTriaFirstAvailable = iTriaLastUsed + 1;
  996.  
  997.     // Compter les sommets inutilisés pour ne faire la suite que s'il y en a
  998.     iShift = 0;
  999.  
  1000.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1001.         if (Vertices[iVert].bEnabled == FALSE)
  1002.             iShift++;
  1003.  
  1004.     if (!iShift)
  1005.         return;
  1006.  
  1007.     // Allouer la table de mapping
  1008.     if (!(iMapTo = (int *) malloc((iVertLastUsed + 1) * sizeof(int))))
  1009.     {
  1010.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1011.         return;
  1012.     }
  1013.  
  1014.     // Préinitialiser la table de mapping
  1015.     for (iShift = 0 ; iShift <= iVertLastUsed ; iShift++)
  1016.         iMapTo[iShift] = iShift;
  1017.  
  1018.     // Réindexer les sommets
  1019.     iShift = 0;
  1020.  
  1021.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1022.     {
  1023.         if (Vertices[iVert].bEnabled == FALSE)
  1024.         {
  1025.             while (Vertices[iVert + iShift].bEnabled == FALSE)
  1026.             {
  1027.                 iShift++;
  1028.                 iVertLastUsed--;
  1029.             }
  1030.         }
  1031.  
  1032.         if (iShift)
  1033.         {
  1034.  
  1035.             Vertices[iVert] = Vertices[iVert + iShift];
  1036.             Vertices[iVert + iShift].bEnabled = Vertices[iVert + iShift].bSelected = FALSE;
  1037.             iMapTo[iVert + iShift] = iVert;
  1038.         }
  1039.  
  1040.     }
  1041.  
  1042.     iVertFirstAvailable = iVertLastUsed + 1;
  1043.  
  1044.     // Réindexer les sommets dans les arêtes
  1045.     for(iShift = 0 ; iShift <= iEdgeLastUsed ; iShift++)
  1046.     {
  1047.         Edges[iShift].iSommets[0] = iMapTo[Edges[iShift].iSommets[0]];
  1048.         Edges[iShift].iSommets[1] = iMapTo[Edges[iShift].iSommets[1]];
  1049.     }
  1050.  
  1051.     // Réindexer les sommets dans les triangles
  1052.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1053.     {
  1054.         Triangles[iShift].iSommets[0] = iMapTo[Triangles[iShift].iSommets[0]];
  1055.         Triangles[iShift].iSommets[1] = iMapTo[Triangles[iShift].iSommets[1]];
  1056.         Triangles[iShift].iSommets[2] = iMapTo[Triangles[iShift].iSommets[2]];
  1057.     }
  1058.  
  1059.     // Libérer la table
  1060.     free(iMapTo);
  1061. }
  1062.